package de.szut.gui.language;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * Manages the languages
 * @author Marc Huisinga
 *
 */

public class Languages {
	/**
	 * Default language
	 */
	public static final String LANGUAGE = "English";
	/**
	 * Default available languages
	 */
	public static final ArrayList<String> LANGUAGES = new ArrayList<String>();
	static {
		LANGUAGES.add("English");
	}
	/**
	 * Default filepath for languagefiles
	 */
	public static final String FILEPATHPREFIX = "lng/";
	/**
	 * Default error that shows if the respective component wasn't found
	 */
	public static final String ERRORONNOTRANSLATION = "#!trans";
	/**
	 * Filename of the template where translation keys get saved upon error
	 */
	public static final String TEMPLATEFILENAME = "language_errors.txt";

	private String currentLanguage;
	private String filePathPrefix;
	private String templateFileName;
	private ArrayList<String> languages;
	private Properties languageProperties;
	private String errorOnNoTranslation;

	/**
	 * Returns the names of the languages that are available
	 * @return names of the languages that are available
	 */
	public ArrayList<String> getLanguages() {
		return languages;
	}
	
	/**
	 * Sets the names of the languages that are available
	 * @param languages names of the languages that are available
	 */
	public void setLanguages(ArrayList<String> languages) {
		this.languages = languages;
	}

	/**
	 * Adds a language to the List of languages that are avilable
	 * @param language language name
	 */
	public void addLanguage(String language) {
		languages.add(language);
	}

	/**
	 * Returns the file path of the language folder
	 * @return file path of the language folder
	 */
	public String getFilePathPrefix() {
		return filePathPrefix;
	}

	/**
	 * Sets the file path of the language folder
	 * @param filePathPrefix file path of the language folder
	 */
	public void setFilePathPrefix(String filePathPrefix) {
		this.filePathPrefix = filePathPrefix;
	}

	/**
	 * Gets the name of the language that is currently selected
	 * @return name of the language that is currently selected
	 */
	public String getCurrentLanguage() {
		return currentLanguage;
	}

	/**
	 * Sets the current language and refreshes the filepointer to the current language
	 * @param currentLanguage Name of the new language
	 */
	public void setCurrentLanguage(String currentLanguage) {
		this.currentLanguage = currentLanguage;
		File currentLanguageFile = new File(filePathPrefix + this.currentLanguage.toLowerCase() + ".ini");
		try {
			languageProperties.clear();
			currentLanguageFile.createNewFile();
			languageProperties.load(new BufferedInputStream(new FileInputStream(currentLanguageFile)));
		} catch (FileNotFoundException e) {
			System.err.println("File " + currentLanguageFile.getAbsolutePath() + " could not be found!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Gets the name of the file where keys are being noted
	 * @return name of the template
	 */
	public String getTemplateFileName() {
		return templateFileName;
	}

	/**
	 * Sets the name of the file where keys are being noted
	 * @param templateFileName
	 */
	public void setTemplateFileName(String templateFileName) {
		this.templateFileName = templateFileName;
	}

	/**
	 * Gets the error message that is inserted instead of nothing
	 * @return error message
	 */
	public String getErrorOnNoTranslation() {
		return errorOnNoTranslation;
	}

	/**
	 * Sets the error message that is inserted instead of nothing
	 * @param errorOnNoTranslation error message
	 */
	public void setErrorOnNoTranslation(String errorOnNoTranslation) {
		this.errorOnNoTranslation = errorOnNoTranslation;
	}

	public Languages() {
		languageProperties = new Properties();
		filePathPrefix = FILEPATHPREFIX;
		languages = LANGUAGES;
		templateFileName = TEMPLATEFILENAME;
		errorOnNoTranslation = ERRORONNOTRANSLATION;
		setCurrentLanguage(LANGUAGE);
		clearTemplate();
	}
	
	/**
	 * Clears the content of the template
	 */
	private void clearTemplate() {
		File templateFile = new File(filePathPrefix + templateFileName);
		try {
			templateFile.createNewFile();
			BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(templateFile));
			bufferedOutputStream.write(0);
			bufferedOutputStream.close();
		} catch (FileNotFoundException e) {
			System.err.println("Generation of template at " + templateFile.getAbsolutePath() + " failed.");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Translates a list of components
	 * @param components components that are supposed to get translated
	 */
	public void translateListOfComponents(List<TranslatableComponent> components) {
		for (TranslatableComponent currentComponent : components) {
			currentComponent.translate(languageProperties.getProperty(currentComponent.getTranslationKey(), ERRORONNOTRANSLATION));
			generateTemplateOnError(currentComponent);
		}
	}
	
	/**
	 * Translates a specific component
	 * @param component that is supposed to het translated
	 */
	public void translateSpecificComponent(TranslatableComponent component) {
		component.translate(languageProperties.getProperty(component.getTranslationKey(),ERRORONNOTRANSLATION));
		generateTemplateOnError(component);
	}
	
	private void generateTemplateOnError(TranslatableComponent comp) {
		if (comp.getTranslation().equals(ERRORONNOTRANSLATION)) {
			Properties templateProperties = new Properties();
			File templateFile = new File(filePathPrefix + templateFileName);
			try {
				templateFile.createNewFile();
				templateProperties.load(new BufferedInputStream(new FileInputStream(templateFile)));
				if (!templateProperties.containsKey(comp.getTranslationKey())) {
					templateProperties.clear();
					templateProperties.put(comp.getTranslationKey(), "");
					BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(templateFile,true));
					templateProperties.store(outputStream, null);
					templateProperties.clear();
					outputStream.close();
				}
			} catch (FileNotFoundException e) {
				System.err.println("Generation of template at " + templateFile.getAbsolutePath() + " failed.");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Wrapper for preparing a component.
	 * Adds a key to the component and the component to the list.
	 * @param key key for the component
	 * @param comp component
	 * @param list list for the component
	 */
	public static void prepareComponent(String key, TranslatableComponent comp, ArrayList<TranslatableComponent> list) {
		comp.setTranslationKey(key);
		list.add(comp);
	}
}
